﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Shsc.Net.Common.Validator.Attributes;
using Shsc.Net.Common.Dto;
using Shsc.Net.Common.Exeption;

namespace Shsc.Net.Common.Validator
{
    public class Validator
    {
        /// <summary>
        /// 对象描述记录
        /// </summary>
        private static IDictionary<string, IDictionary<string, ObjectDesciption>> PropertyDesciption =
            new Dictionary<string, IDictionary<string, ObjectDesciption>>();

        /// <summary>
        /// 
        /// </summary>
        private static readonly object lockKey1 = new object();

        /// <summary>
        /// 
        /// </summary>
        private static readonly object lockKey2 = new object();

        /// <summary>
        /// 对象描述
        /// </summary>
        private class ObjectDesciption
        {
            /// <summary>
            /// 属性名
            /// </summary>
            public string PropertyName { get; set; }

            /// <summary>
            /// 属性的特性List
            /// </summary>
            public List<BaseValidationAttribute> ValidatorAttribute { get; set; }

        }

        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="lstValidatorResut"></param>
        public static void DoValidator(BaseDto dto,
            ValidatorResultList lstValidatorResut,
            params string[] tagetAction)
        {
            if (!(dto is BaseDto)) return;

            //获取Check对象类型
            Type type = dto.GetType();
            string key = type.Namespace + "." + type.Name;
            IDictionary<string, ObjectDesciption> objDesciption = null;

            //查看缓存中对象信息是否存在
            if (PropertyDesciption.ContainsKey(key))
            {
                objDesciption = PropertyDesciption[key];
            }
            
            if (objDesciption == null)
            {
                lock (lockKey1)
                {
                    if (objDesciption == null)
                    {
                        objDesciption = new Dictionary<string, ObjectDesciption>();
                        PropertyDesciption.Add(key, objDesciption);
                    }
                }
            }

            //获取对象属性
            PropertyInfo[] properties = type.GetProperties();
            foreach (PropertyInfo propertyInfo in properties)
            {
                //属性ID
                string propertyId = propertyInfo.Name;
                //属性值
                object propertyvalue = propertyInfo.GetValue(dto, null);

                //判断特性
                ObjectDesciption propertyDesscirpt = null;
                if (objDesciption.ContainsKey(propertyId))
                {
                    propertyDesscirpt = objDesciption[propertyId];
                }
                //缓存对象属性信息
                List<BaseValidationAttribute> ValidatorAttribute = null;
                if (propertyDesscirpt == null)
                {
                    lock (lockKey2)
                    {
                        if (propertyDesscirpt == null)
                        {
                            //获取属性的特性
                            Attribute[] attributes
                                = propertyInfo.GetCustomAttributes(typeof(Attribute), true) as Attribute[];

                            propertyDesscirpt = new ObjectDesciption();
                            propertyDesscirpt.ValidatorAttribute = new List<BaseValidationAttribute>();
                            foreach (Attribute attribute in attributes)
                            {
                                if (attribute is BaseValidationAttribute)
                                {
                                    propertyDesscirpt.ValidatorAttribute.Add(attribute as BaseValidationAttribute);
                                }
                            }
                            objDesciption.Add(propertyId, propertyDesscirpt);
                        }
                    }
                }

                //对象属性根据注释Check
                ValidatorAttribute = propertyDesscirpt.ValidatorAttribute;

                foreach (BaseValidationAttribute attribute in ValidatorAttribute)
                {
                    if ((tagetAction != null
                        && tagetAction.Length == 1
                        && attribute.TagerAction.Contains(tagetAction[0]))
                        || (tagetAction == null || tagetAction.Length == 0))
                    {
                        attribute.DoValidate(
                            propertyId,
                            propertyvalue,
                            propertyDesscirpt.PropertyName,
                            dto.Language,
                            lstValidatorResut);
                    }
                }
            }

            if (lstValidatorResut.Count > 0)
            {
                ValidatorException ex = new ValidatorException();
                ex.ValidatorResultList = lstValidatorResut;
                throw ex;
            }
        }
    }
}
